﻿using System;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using HighDiveEngine.Aggregates;
using HighDiveEngine.Model;
using HighDiveEngine.Resources;

namespace HighDiveAdmin.GUI.Components
{
    public partial class EditContestNewDiverPanel : UserControl
    {
        public event DelegateVoidPersonEventArgsDiveEventArgsArray EventSaveDiver;
        public event DelegateVoidString EventLoadDiver;
        public event MethodInvoker EventDiscard;
        //public event DelegateVoidStringString EventCalculateDifficulty;
        public event DelegateDoubleStringInt EventCalculateDifficulty;

        private int gotoColumn;
        private int gotoRow;

        #region Constructor
        public EditContestNewDiverPanel()
        {
            InitializeComponent();
        }
        #endregion

        #region Fill Methods

        public void FillDiverInfo(PersonList personList)
        {
            var strcol = new AutoCompleteStringCollection();
            foreach (var person in personList)
            {
                if (person.IdNumber != null)
                    strcol.Add(person.IdNumber);
            }
            textBoxIdNumber.AutoCompleteCustomSource = strcol;
        }

        public void FillExistingDiverFromIdNumber(Person person)
        {
            textBoxClub.Text = person.Club;
            textBoxFirstName.Text = person.FirstName;
            textBoxLastName.Text = person.LastName;
            comboBoxGender.Text = person.Gender.ToString();
            textBoxAddress.Text = person.Address;
            textBoxEmail.Text = person.Email;

            textBoxFirstName.Enabled = false;
            textBoxLastName.Enabled = false;
            comboBoxGender.Enabled = false;
        }

        #endregion

        public void Show(Diver diver, DiveList diveList)
        {
            if (diver.IdNumber != null)
            {
                textBoxIdNumber.Enabled = false;
                textBoxClub.Enabled = true;
                textBoxAddress.Enabled = true;
                textBoxEmail.Enabled = true;
                dataGridDiveList.Enabled = true;

                textBoxIdNumber.Text = diver.IdNumber;
                textBoxFirstName.Text = diver.FirstName;
                textBoxLastName.Text = diver.LastName;
                comboBoxGender.Text = diver.Gender.ToString();
                textBoxClub.Text = diver.Club;
                textBoxAddress.Text = diver.Address;
                textBoxEmail.Text = diver.Email;

                dataGridDiveList.Rows.Clear();
                foreach (var dive in diveList)
                {
                    dataGridDiveList.Rows.Add(dive.DiveNumber, dive.DiveCode, dive.DiveHeight, dive.Difficulty);
                }
                
            }
            else
            {
                textBoxIdNumber.Enabled = true;
                textBoxFirstName.Enabled = false;
                textBoxLastName.Enabled = false;
                comboBoxGender.Enabled = false;
                textBoxClub.Enabled = false;
                textBoxAddress.Enabled = false;
                textBoxEmail.Enabled = false;
                dataGridDiveList.Enabled = false;
            }
            dataGridDiveList.Rows.Add((dataGridDiveList.Rows.Count + 1).ToString());
            labelNumber.Text = diver.StartNumber.ToString();
            Visible = true;
        }

        #region Button Click Events

        private void textBoxIdNumber_Leave(object sender, EventArgs e)
        {
            if (textBoxIdNumber.Text.Length == 10)
            {
                if (new Regex(@"^[0-9]{10}$").IsMatch(textBoxIdNumber.Text))
                {
                    _clearText();

                    try
                    {
                        textBoxFirstName.Enabled = true;
                        textBoxLastName.Enabled = true;
                        comboBoxGender.Enabled = true;

                        //attempt auto complete from database
                        if (EventLoadDiver != null)
                            EventLoadDiver(textBoxIdNumber.Text);

                        
                        textBoxClub.Enabled = true;
                        textBoxAddress.Enabled = true;
                        textBoxEmail.Enabled = true;
                        dataGridDiveList.Enabled = true;

                        comboBoxGender.Text = "Male";

                        //set focus
                        if (comboBoxGender.Enabled)
                            comboBoxGender.Focus();
                        else
                            textBoxAddress.Focus();
                    }
                    catch (Exception exception)
                    {
                        textBoxFirstName.Enabled = false;
                        textBoxLastName.Enabled = false;
                        comboBoxGender.Enabled = false;
                        toolTipError.Show(exception.Message, textBoxIdNumber, 30, 20, 5000);
                    }
                }
            }
        }

        private void _clearText()
        {            
            textBoxAddress.Text = "";
            textBoxClub.Text = "";
            textBoxEmail.Text = "";
            textBoxFirstName.Text = "";
            textBoxLastName.Text = "";
            dataGridDiveList.Rows.Clear();
            dataGridDiveList.Rows.Add((dataGridDiveList.Rows.Count + 1).ToString());
        }

        private void buttonDiscard_Click(object sender, EventArgs e)
        {
            if (EventDiscard != null)
            {
                textBoxIdNumber.Text = "";
                _clearText();
                EventDiscard();
            }
        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            #region Regex Checks

            if (!(new Regex(@"^[0-9]{10}$").IsMatch(textBoxIdNumber.Text)))
            {
                MessageBox.Show("Invalid social security number");
                return;
            }
            if (!(new Regex(@"^[a-zA-ZåäöüÅÄÖ]+$").IsMatch(textBoxFirstName.Text)))
            {
                MessageBox.Show("Please enter a valid first name");
                return;
            }
            if (!(new Regex(@"^[a-zA-ZåäöüÅÄÖ]+$").IsMatch(textBoxLastName.Text)))
            {
                MessageBox.Show("Please enter a valid last name");
                return;
            }
            if (!(new Regex(@"^([a-zA-ZåäöüÅÄÖ 0-9]+)?$").IsMatch(textBoxAddress.Text)))
            {
                MessageBox.Show("Please enter a valid adress");
                return;
            }
            if (!(new Regex(@"^([A-Za-z0-9]+@([A-Za-z0-9]+\.)+[A-Za-z]{2,3})?$").IsMatch(textBoxEmail.Text)))
            {
                MessageBox.Show("Please enter a valid email adress");
                return;
            }
            if (!(new Regex(@"^([a-zA-ZåäöüÅÄÖ 0-9]+)?$").IsMatch(textBoxClub.Text)))
            {
                MessageBox.Show("Please enter a valid club");
                return;
            }
            if (dataGridDiveList.Rows.Count <= 1)
            {
                MessageBox.Show("Please enter atleast one dive");
                return;
            }

            for (int i = 0; i < dataGridDiveList.Rows.Count - 1; i++)   //last row is always empty
            {
                if (dataGridDiveList.Rows[i].Cells[3].Value == null)
                {
                    MessageBox.Show("Dive " + (i + 1) + " is invalid");
                    return;
                }

                if (dataGridDiveList.Rows[i].Cells[1].Value != null)
                {
                    if (!(new Regex(@"^[0-9]{3,4}[a-zA-Z]$").IsMatch(dataGridDiveList.Rows[i].Cells[1].Value.ToString())))
                    {
                        MessageBox.Show("Invalid Dive Code on dive " + (i + 1));
                        return;
                    } 
                }
                else
                {
                    MessageBox.Show("Invalid Dive Code on dive " + (i + 1));
                    return;
                }


                if (dataGridDiveList.Rows[i].Cells[2].Value != null)
                {
                    if (!(new Regex(@"^([1]([0])?)|[3]|[5]|[7]$").IsMatch(dataGridDiveList.Rows[i].Cells[2].Value.ToString())))
                    {
                        MessageBox.Show("Invalid height on dive " + (i + 1));
                        return;
                    } 
                }
                else
                {
                    MessageBox.Show("Invalid height on dive " + (i + 1));
                    return;
                }

            }

            #endregion
            
            DiverEventArgs personArgs = new DiverEventArgs
            {
                IdNumber = textBoxIdNumber.Text,
                FirstName = textBoxFirstName.Text,
                LastName = textBoxLastName.Text,
                Gender = (Gender)Enum.Parse(typeof(Gender), comboBoxGender.Text),
                Address = textBoxAddress.Text,
                Email = textBoxEmail.Text,
                Club = textBoxClub.Text,
                StartNumber = Convert.ToInt32(labelNumber.Text)
            };

            DiveEventArgs[] diveArgs = new DiveEventArgs[dataGridDiveList.Rows.Count - 1];  //last row is always empty
            for (int i = 0; i < diveArgs.Length; i++)
            {
                diveArgs[i] = new DiveEventArgs
                {
                    DiveNumber = Convert.ToInt32(dataGridDiveList.Rows[i].Cells[0].Value),
                    DiveCode = dataGridDiveList.Rows[i].Cells[1].Value.ToString(),
                    DiveHeight = Convert.ToInt32(dataGridDiveList.Rows[i].Cells[2].Value),
                    Difficulty = Convert.ToDouble(dataGridDiveList.Rows[i].Cells[3].Value)
                };
                
            }
            Visible = false;
            if (EventSaveDiver != null)
            {
                textBoxIdNumber.Text = "";
                _clearText();
                EventSaveDiver(personArgs, diveArgs);
            }
                
        }

        /// <summary>
        /// This method triggers an event that fills the difficulty cell on a row after both the dive code and
        /// height has been entered.
        /// </summary>
        private void dataGridDiveList_RowLeave(object sender, DataGridViewCellEventArgs e)
        {
            if (dataGridDiveList.Rows[e.RowIndex].Cells[1].Value != null && dataGridDiveList.Rows[e.RowIndex].Cells[2].Value != null)
            {
                if (new Regex(@"^[0-9]{3,4}[a-zA-Z]$").IsMatch(dataGridDiveList.Rows[e.RowIndex].Cells[1].Value.ToString()) &&
                    new Regex(@"^([1]([0])?)|[3]|[5]|[7]$").IsMatch(dataGridDiveList.Rows[e.RowIndex].Cells[2].Value.ToString()))
                {
                    if (EventCalculateDifficulty != null)
                        try
                        {
                            dataGridDiveList.Rows[e.RowIndex].Cells[3].Value =
                                EventCalculateDifficulty(dataGridDiveList.Rows[e.RowIndex].Cells[1].Value.ToString(),
                                    Convert.ToInt32(dataGridDiveList.Rows[e.RowIndex].Cells[2].Value));
                        }
                        catch (DiveCodeException d)
                        {
                            toolTipError.Show(d.Message, labelDiveList, 80, 22 * e.RowIndex + 55, 5000);
                        }
                }
            }

        }

        private void dataGridDiveList_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (dataGridDiveList.Rows.Count > 0)
            {
                switch (e.ColumnIndex)
                {
                    case 0:
                        gotoColumn = 1;
                        gotoRow = e.RowIndex;
                        Application.Idle += Application_Idle;
                        break;
                    case 1:
                        break;
                    case 2:
                        break;
                    case 3:
                        gotoColumn = 1;

                        //check to see if current row has values
                        if (dataGridDiveList.Rows[e.RowIndex].Cells[1].Value != null &&
                            dataGridDiveList.Rows[e.RowIndex].Cells[2].Value != null)
                        {
                            gotoRow = e.RowIndex + 1;
                        }
                        else
                        {
                            gotoRow = e.RowIndex;
                        }
                        
                        Application.Idle += Application_Idle;
                        break;
                }
            }
        }

        void Application_Idle(object sender, EventArgs e)
        {
            Application.Idle -= Application_Idle;            
            if (gotoRow == dataGridDiveList.Rows.Count)  //last row, add new
            {
                dataGridDiveList.Rows.Add((dataGridDiveList.Rows.Count + 1).ToString());
            }
            dataGridDiveList.CurrentCell = dataGridDiveList[gotoColumn, gotoRow];
        }

        #endregion       
        
        #region TabStop

        private void EditContestNewDiverPanel_TabStopChanged(object sender, EventArgs e)
        {
            foreach (Control control in Controls)
                control.TabStop = TabStop;
            if (TabStop)
                textBoxIdNumber.Focus();
        }

        private void EditContestNewDiverPanel_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible)
                textBoxIdNumber.Focus();
        }
        #endregion
    }
}
